cmake_minimum_required(VERSION 3.0)

project(spark LANGUAGES Fortran)

option(SPARK_RUN_TEST "Run SPARK unit tests" OFF)

if (NOT DEFINED SPARK_I_KIND)
  set(SPARK_I_KIND 4)
endif ()
if (NOT DEFINED SPARK_R_KIND)
  set(SPARK_R_KIND 8)
endif ()

add_definitions(-DI_KIND=${SPARK_I_KIND})
add_definitions(-DR_KIND=${SPARK_R_KIND})

if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
  set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-none -ffpe-trap=invalid,zero,overflow")
  if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -O0 -fcheck=all -g -fbacktrace")
  else ()
    set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Ofast")
  endif ()
  # FIXME: OpenMP causes sigmentation faults.
  # set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fopenmp")
elseif (CMAKE_Fortran_COMPILER_ID STREQUAL "Intel")
  if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -no-wrap-margin -O0 -check bounds -g -traceback")
  else ()
    set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -no-wrap-margin -O3")
  endif ()
endif ()
set(CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}")

get_directory_property(parent_dir PARENT_DIRECTORY)

if (DEFINED ENV{NETCDF} AND (NOT DEFINED ENV{NETCDF_ROOT}))
  set(ENV{NETCDF_ROOT} $ENV{NETCDF})
endif ()
if (DEFINED ENV{NETCDF_ROOT})
  if (NOT parent_dir)
    message(STATUS "Use netCDF in $ENV{NETCDF_ROOT}.")
  endif ()
  include_directories("$ENV{NETCDF_ROOT}/include")
  link_directories("$ENV{NETCDF_ROOT}/lib")
else ()
  find_package(PkgConfig)
  if (PKG_CONFIG_FOUND)
    pkg_search_module(NETCDF REQUIRED netcdf)
    if (NETCDF_FOUND)
      include_directories(${NETCDF_INCLUDEDIR})
      link_directories(${NETCDF_LIBDIR})
    else ()
      message(FATAL_ERROR "Pkg-config could not find netcdf library!")
    endif ()
  else ()
    message(FATAL_ERROR "Unable to find pkg-config library!")
  endif ()
endif ()
list(APPEND EXTERNAL_LIBS netcdff)

if (SPARK_RUN_TEST)
  add_subdirectory(lib/unit-test)
  list(APPEND EXTERNAL_LIBS fortran_unit_test)
endif ()
if (EXISTS ${PROJECT_SOURCE_DIR}/lib/container/CMakeLists.txt AND NOT parent_dir)
  add_subdirectory(lib/container)
endif ()
if (EXISTS ${PROJECT_SOURCE_DIR}/lib/string/CMakeLists.txt AND NOT parent_dir)
  add_subdirectory(lib/string)
endif ()
if (EXISTS ${PROJECT_SOURCE_DIR}/lib/flogger/CMakeLists.txt AND NOT parent_dir)
  add_subdirectory(lib/flogger)
endif ()
if (EXISTS ${PROJECT_SOURCE_DIR}/lib/fiona/CMakeLists.txt AND NOT parent_dir)
  add_subdirectory(lib/fiona)
endif ()

set(sources
  src/kinds_mod.F90
  src/mesh_const_mod.F90
  src/physics_const_mod.F90
  src/gauss_quad_mod.F90
  src/mesh_math_mod.F90
  src/var_types_mod.F90
  src/cubed_sphere/cubed_sphere_math_mod.F90
  src/cubed_sphere/cubed_sphere_domain_mod.F90
  src/cubed_sphere/cubed_sphere_mesh_mod.F90
  src/cubed_sphere/cubed_sphere_halo_mod.F90
  src/cubed_sphere/cubed_sphere_domain_array_mod.F90
  src/cubed_sphere/cubed_sphere_array_mod.F90
  src/cubed_sphere/cubed_sphere_process_mod.F90
  src/cubed_sphere/cubed_sphere_parallel_mod.F90
  src/cubed_sphere/cubed_sphere_objects.F90
  src/spark_cubed_sphere.F90
  src/latlon/latlon_mesh_mod.F90
  src/latlon/latlon_halo_mod.F90
  src/latlon/latlon_array_mod.F90
  src/latlon/latlon_process_mod.F90
  src/latlon/latlon_parallel_mod.F90
  src/latlon/latlon_objects.F90
  src/spark_latlon.F90
)

find_package(MPI)
if (MPI_FOUND)
  add_definitions(-DHAS_MPI)
endif ()

add_library(spark ${sources})
target_link_libraries(spark ${EXTERNAL_LIBS} fortran_container fortran_string flogger fiona)

if (SPARK_RUN_TEST)
  add_executable(test_cubed_sphere_mesh.exe src/test/test_cubed_sphere_mesh.F90)
  target_link_libraries(test_cubed_sphere_mesh.exe spark)

  add_executable(test_cubed_sphere_array.exe src/test/test_cubed_sphere_array.F90)
  target_link_libraries(test_cubed_sphere_array.exe spark)

  add_executable(test_cubed_sphere_halo.exe src/test/test_cubed_sphere_halo.F90)
  target_link_libraries(test_cubed_sphere_halo.exe spark)

  add_executable(test_cubed_sphere_process.exe src/test/test_cubed_sphere_process.F90)
  target_link_libraries(test_cubed_sphere_process.exe spark)

  add_executable(test_cubed_sphere_parallel.exe src/test/test_cubed_sphere_parallel.F90)
  target_link_libraries(test_cubed_sphere_parallel.exe spark)
endif ()
